package com.tbit.uqbike.task;

import com.tbit.uqbike.TerGatewayMain;
import com.tbit.uqbike.protocol.AnalyzeImpl.AAutoProtocol;
import com.tbit.uqbike.protocol.AnalyzeImpl.AProtocol;
import com.tbit.uqbike.service.redis.RedisService;
import com.tbit.uqbike.tergateway.data.TerGatewayData;
import com.tbit.uqbike.tergateway.entity.AConnInfo;
import com.tbit.uqbike.tergateway.entity.RemoteControl;
import com.tbit.uqbike.tergateway.entity.TerTempData;
import io.netty.buffer.ByteBuf;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by MyWin on 2018/4/17 0017.
 */
public class DelayOfflineOrder implements Runnable {
    private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DelayOfflineOrder.class);

    private TreeMap<RemoteControl, String> offlineOrderList = new TreeMap<>(new RemoteControlComparator());
    private Map<String, RemoteControl> serMap = new HashMap<>();

    private ReentrantLock lock = new ReentrantLock();

    public void addOfflineOrder(RemoteControl remoteControl, String redisStr) {
        try {
            lock.lock();

            if (!serMap.containsKey(remoteControl.serNO)) {
                offlineOrderList.put(remoteControl, redisStr);
                serMap.put(remoteControl.serNO, remoteControl);
            }
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void run() {
        try {
            RedisService redis = TerGatewayMain.getRedis();
            try {
                lock.lock();

                Long now = System.currentTimeMillis();
                Long lastControlDt = 0L;
                while (true) {
                    if (offlineOrderList.isEmpty()) {
                        break;
                    }
                    now = System.currentTimeMillis();
                    Map.Entry<RemoteControl,String> kv = offlineOrderList.firstEntry();
                    RemoteControl control = kv.getKey();
                    lastControlDt = control.planDownDt;
                    // 如果时间未到，等待下次检测
                    if (lastControlDt > now) {
                        break;
                    } else {
                        logger.info(String.format("dt:%d,sn:%s,size:%d", control.planDownDt, control.sn, offlineOrderList.size()));

                        String redisKey = String.format("%s.%s", TerGatewayData.REIDS_ORDER_LIST_TER, control.sn);

                        TerTempData terTempData = TerGatewayData.tryGetTerTempDataByMno(control.sn);
                        if (terTempData != null) {
                            AConnInfo info = terTempData.getConnInfo();
                            if (null != info) {
                                AProtocol protocol = AAutoProtocol.getProtocol(terTempData.protocolName);
                                if (null != protocol) {
                                    final ByteBuf byteBuf = protocol.builtRemoteControlPkg(info, control);
                                    // 最后发送下行数据
                                    if (byteBuf != null && byteBuf.readableBytes() > 0) {
                                        TerGatewayData.addOrderTimeOutCheck(control);
                                        info.downMsg(byteBuf);
                                        // 发送成功更新下行时间
                                        TerGatewayMain.getDbService().updateOfflineOrderDownDt(control.serNO, new Date());
                                        // 删除缓存
                                        redis.LDelValue(redisKey, 0, kv.getValue());
                                    }
                                }
                            }
                        }

                        offlineOrderList.pollFirstEntry();
                        serMap.remove(control.serNO);

                    }
                }
            } finally {
                lock.unlock();
            }
        } catch (Exception e) {
            logger.error("DelayOfflineOrder", e);
        }
    }

    public static void main(String[] args) {

    }
}
